#ifndef TYPESYSTEMIMPL_H
#define TYPESYSTEMIMPL_H
#include "StompedReality/Core.h"
#include "StompedReality/Core/Logger.h"
#include "TypeField.h"
#include "TypeInfo.h"
#include <map>
namespace StompedReality
{
namespace type_system
{
class DLL_EXPORT TypeSystemImpl
{
  typedef std::map<StompedReality::TYPE_ID, TypeInfo*> TypeInfoMap;

 protected:

  TypeInfoMap _typeMap;
  TypeInfoMap _nameInfoMap;

 public:

  TypeSystemImpl( );
  virtual ~TypeSystemImpl( );

  //!	\brief Creates a new typ.
  //! \param name Type name.
  //! \return TypeInfo.
  template <typename TYPE>
  TypeInfo* CreateTypeInfo ( const char* name );

  //!	\brief Type exits?
  //!	\param	typeID	The type id
  bool HasType ( StompedReality::TYPE_ID typeID );

  //!	\brief Type exits?
  //!	\param	typeName	typeName
  bool HasType ( const char* typeName );

  //!	\brief Type info getter
  //!	\param	typeID	The type id
  TypeInfo* GetType ( StompedReality::TYPE_ID typeID );

  //!	\brief Type info getter
  //!	\param	typeName	typeName
  TypeInfo* GetType ( const char* typeName );

  //!	\brief Type info getter
  StompedReality::TYPE_ID GetTypeID ( const char* typeName );

  //!	\brief Type info getter
  template <typename TYPE>
  StompedReality::TYPE_ID GetTypeID( );

  //!	\brief Type info getter
  template <typename TYPE>
  TypeInfo* GetType( );

  //!	\brief Type exits?
  template <typename TYPE>
  bool HasType( );
};

template <typename TYPE>
TypeInfo* TypeSystemImpl::CreateTypeInfo ( const char* name )
{
  TypeInfo* type = new TypeInfo ( name );
  type->typeID = StompedReality::hash ( typeid ( TYPE ).name( ) );
  type->size = sizeof ( TYPE );
  type->constructor = &defaultConstructor<TYPE>;
  type->destructor = &defaultDestructor<TYPE>;
  type->newPtr = &defaultNew<TYPE>;

  this->_typeMap[type->typeID] = type;
  this->_nameInfoMap[StompedReality::hash ( type->name ) ] = type;

  LogCallFunctionInfo( "TypeSystem", "createTypeInfo" );
  LogInfoPair( "name", name );
  LogInfoPair( "size", type->size );

  return type;
}

template <typename TYPE>
StompedReality::TYPE_ID TypeSystemImpl::GetTypeID( )
{
  return StompedReality::hash ( typeid ( TYPE ).name( ) );
}

template <typename TYPE>
bool TypeSystemImpl::HasType( )
{
  return this->HasType ( StompedReality::hash ( typeid ( TYPE ).name( ) ) );
}

template <typename TYPE>
TypeInfo* TypeSystemImpl::GetType( )
{
  return this->GetType ( StompedReality::hash ( typeid ( TYPE ).name( ) ) );
}

}
}
#endif // TYPESYSTEMIMPL_H
